package net.gazhi.delonix.core.init;

import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.SmartLifecycle;

/**
 * 初始化调用器
 * 
 * @author Jeffrey Lin
 *
 */
public class InitExecuter implements SmartLifecycle, ApplicationContextAware {

	private Logger logger = LogManager.getLogger();

	@Autowired
	private ApplicationContext applicationContext;

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	}

	@Override
	public void start() {

		TreeSet<InitService> services = new TreeSet<InitService>();
		services.addAll(applicationContext.getBeansOfType(InitService.class).values());
		List<InitService> finishServices = new ArrayList<InitService>(services.size());

		// 对于因条件未成熟没有成功执行的 service，通过多次尝试的方式执行
		while (services.size() > 0) {
			for (InitService service : services) {
				try {
					if (service.checkAndDoInit()) {
						service.setFinished();
						finishServices.add(service);
					}
				} catch (Exception e) {
					logger.error("执行自动初始化失败：" + e.getMessage());
					throw new RuntimeException(e);
				}
			}
			if (finishServices.size() == 0) {
				throw new RuntimeException("Fail to run InitExecuter, none InitService is finished.");
			}
			services.removeAll(finishServices);
			finishServices.clear();
		}

	}

	@Override
	public void stop() {
	}

	@Override
	public boolean isRunning() {
		return false;
	}

	@Override
	public int getPhase() {
		return 0;
	}

	@Override
	public boolean isAutoStartup() {
		return true;
	}

	@Override
	public void stop(Runnable callback) {
	}

}
